package cn.leedsoft.luma.common.utils;

import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.*;
import org.icepdf.core.pobjects.Document;
import org.icepdf.core.pobjects.Page;
import org.icepdf.core.util.GraphicsRenderingHints;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

/**
 * Created by Administrator on 2016/11/23.
 */
public class PdfUtil {
    public static class Scale {//png图片缩放比例
        public static final float SMALL = 0.5f;
        public static final float NORMAL = 1.5f;
        public static final float LARGE = 2.5f;
    }

    private static final Logger logger = LoggerFactory.getLogger(PdfUtil.class);

    private static BaseFont simsun;
    private static Font simsunFont;
    static {
        try {
            simsun = BaseFont.createFont("fonts/simsun.ttc,1", BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
            simsunFont = new Font(simsun);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成一个由png图片字节数组构成的list。
     * 图片在list中的位置，对应pdf的页面位置
     *
     * @param tplIn
     * @param fields
     * @param scale
     * @return
     */
    public static List<byte[]> genPngByPdfTpl(InputStream tplIn, Map<String, Object> fields, float scale) {
        return convertPdf2Png(new ByteArrayInputStream(genPdfByTpl(tplIn, fields)), scale);
    }
    public static List<byte[]> genPngByPdfTpl(InputStream tplIn, Map<String, Object> fields) {
        return genPngByPdfTpl(tplIn, fields, Scale.NORMAL);
    }
    public static List<byte[]> convertPdf2Png(InputStream pdfIn) {
        return convertPdf2Png(pdfIn, Scale.NORMAL);
    }

    /**
     * 只将pdf的page 1 转为图片字节数组，并返回。（常用于单页打印）
     * @param tplIn
     * @param fields
     * @return
     */
    public static byte[] genPngPage1(InputStream tplIn, Map<String, Object> fields) {
        List<byte[]> pngs = genPngByPdfTpl(tplIn, fields);
        return pngs.size() > 0 ? pngs.get(0) : null;
    }
    public static List<byte[]> convertPdf2Png(InputStream pdfIn, float scale) {
        List<byte[]> res = Lists.newArrayList();
        Document document = new Document();
        document.setInputStream(pdfIn, "");
        float rotation = 0f;//旋转角度
        ByteArrayOutputStream byos = new ByteArrayOutputStream(1024 * 1024);
        for (int i = 0; i < document.getNumberOfPages(); i++) {
            BufferedImage image = (BufferedImage)
                    document.getPageImage(i, GraphicsRenderingHints.SCREEN, Page.BOUNDARY_CROPBOX, rotation, scale);

            try {
                ImageIO.write(image, "png", byos);
            } catch (IOException e) {
                e.printStackTrace();
            }
            image.flush();
            byte[] pngBytes = byos.toByteArray();
            byos.reset();
            res.add(pngBytes);
            logger.info(String.format(">>>生成第%1$s页图片字节数组，长度为%2$s:", i + 1, pngBytes.length));
        }
        try {
            byos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        document.dispose();
        return res;
    }

    public static byte[] genPdfByTpl(InputStream tplIn, Map<String, Object> fields) {
        PdfStamper stamper = null;
        ByteArrayOutputStream byos = new ByteArrayOutputStream(1024 * 1024 * 5);//5M
        try {
            PdfReader reader = new PdfReader(tplIn);
            stamper = new PdfStamper(reader, byos);
            AcroFields form = stamper.getAcroFields();
            for (String field : form.getFields().keySet()) {
                if (fields.containsKey(field)) {
                    form.setField(field, String.valueOf(fields.get(field)));
                }
            }
            form.addSubstitutionFont(simsun);
            stamper.setFormFlattening(true);
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (stamper != null) {
                try {
                    stamper.close();//close之后，字节流才写入output stream
                } catch (DocumentException e) {
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        byte[] pdfBytes = byos.toByteArray();
        try {
            byos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        logger.info(">>>生成pdf字节数组，长度为：" + pdfBytes.length);
        return pdfBytes;
    }

    public static class TableDataVo <T> {
        /**
         * required 表头。
         * 1、其顺序，决定了表中列的顺序。
         * 2、二级数组第一列对应数据集的字段名。第二列为表头
         * 3、格式如{{"name", "名字"}, {"age", "年龄"}...}
         */
        private String[][] headers;
        private List<T> datalist = Lists.newArrayList();//required 数据集。
        private int pageNum = 1;//table插入的位置：第几页
        private int topPos = 500;//required . table 插入的位置：table顶部的位置。取值范围为60--700
        private int[] widths;//为空的话，默认等宽。

        public String[][] getHeaders() {
            return headers;
        }

        public void setHeaders(String[][] headers) {
            this.headers = headers;
        }

        public List<T> getDatalist() {
            return datalist;
        }

        public void setDatalist(List<T> datalist) {
            this.datalist = datalist;
        }

        public int getPageNum() {
            return pageNum;
        }

        public void setPageNum(int pageNum) {
            this.pageNum = pageNum;
        }

        public int getTopPos() {
            return topPos;
        }

        public void setTopPos(int topPos) {
            this.topPos = topPos;
        }

        public int[] getWidths() {
            return widths;
        }

        public void setWidths(int[] widths) {
            this.widths = widths;
        }
    }

    public static <T> byte[] genPdfWithTableByTpl(InputStream tplIn, Map<String, Object> fields, TableDataVo<T> tableDataVo){
        try {
            PdfReader reader = new PdfReader(tplIn);
            ByteArrayOutputStream byos = new ByteArrayOutputStream(1024 * 1024 * 5);//5M
            PdfStamper stamper = new PdfStamper(reader, byos);
            AcroFields form = stamper.getAcroFields();
            for (String field : form.getFields().keySet()) {
                if (fields.containsKey(field)) {
                    form.setField(field, String.valueOf(fields.get(field)));
                }
            }
            form.addSubstitutionFont(simsun);
            //生成pdftable
            PdfPTable table = new PdfPTable(tableDataVo.getHeaders().length);
            for (String[] header : tableDataVo.getHeaders()) {
                table.addCell(new Paragraph(header[1], simsunFont));
            }
            table.setHeaderRows(1);
            if (tableDataVo.getWidths() != null && tableDataVo.getWidths().length == tableDataVo.getHeaders().length) {
                table.setWidths(tableDataVo.getWidths());//宽度
            }
            for (T dataitem : tableDataVo.getDatalist()) {//一个循环一行数据
                Map<String, Object> m = (Map<String, Object>) JSON.toJSON(dataitem);
                for (String[] header : tableDataVo.getHeaders()) {
                    table.addCell(new Paragraph(String.valueOf(m.get(header[0])), simsunFont));
                }
            }

            Rectangle pagesize = reader.getPageSize(tableDataVo.getPageNum());
            ColumnText column = new ColumnText(stamper.getOverContent(tableDataVo.getPageNum()));
            Rectangle rectPage1 = new Rectangle(36, 36, 559, tableDataVo.getTopPos());//36--700
            column.setSimpleColumn(rectPage1);
            column.addElement(table);
            int pagecount = tableDataVo.getPageNum();
            Rectangle rectPage2 = new Rectangle(36, 36, 559, 806);
            int status = column.go();
            while (ColumnText.hasMoreText(status)) {
                status = triggerNewPage(stamper, pagesize, column, rectPage2, ++pagecount);
            }
            stamper.setFormFlattening(true);
            stamper.close();
            reader.close();
            return byos.toByteArray();
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static int triggerNewPage(PdfStamper stamper, Rectangle pagesize, ColumnText column, Rectangle rect, int pagecount) throws DocumentException {
        stamper.insertPage(pagecount, pagesize);//插入新页面
        PdfContentByte canvas = stamper.getOverContent(pagecount);
        column.setCanvas(canvas);
        column.setSimpleColumn(rect);
        return column.go();
    }
}
